package com.woniuxy.portal.config.interceptor;

import com.woniuxy.common.enums.impl.BusinessCode;
import com.woniuxy.common.exception.Assert;
import com.woniuxy.portal.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {

    private final JwtUtil jwtUtil;

    @Autowired
    public JwtInterceptor(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    /**
     * 请求预处理方法，在请求到达控制器之前进行拦截处理
     * 主要功能：验证OPTIONS预检请求、校验JWT token有效性、验证IP地址一致性
     *
     * @param request  HTTP请求对象，包含客户端请求信息
     * @param response HTTP响应对象，用于向客户端返回数据
     * @param handler  处理器对象，包含即将执行的控制器方法信息
     * @return boolean 返回true表示放行请求，false表示拦截请求
     * @throws Exception 当验证失败或出现异常时抛出
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {

        log.info("拦截器：{}", request.getRequestURI());

        // 放行axios的预检请求：options请求方式
        boolean flag = request.getMethod().equalsIgnoreCase("OPTIONS");
        if (flag) {
            return true; // 放行，不拦截
        }

        // 获取请求头的token并进行有效性验证
        String token = request.getHeader("Authorization");
        // 判断token是否存在
        Assert.error(Objects.isNull(token), BusinessCode.TOKEN_NOT_EXISTS);
        // 验证token是否存在
        Assert.error(!jwtUtil.validateToken(token), BusinessCode.INVALID_TOKEN);

        // 验证token中的IP地址与当前访问者IP是否一致
        String ip = jwtUtil.getValue(token, "ip");
        // 获取当前访问者的ip
        String visitIP = jwtUtil.getRequestIP(request);
        Assert.error(!ip.equals(visitIP), BusinessCode.INVALID_IP);

        return true;
    }

}
